package StructurePattern.Proxy;

/**
 * @author: Themberfue
 * @date: 2025/8/12 10:43
 * @description:
 */
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 1. 抽象主题接口
interface Image {
    void display();
    String getInfo();
}

// 2. 真实主题（目标对象）
class RealImage implements Image {
    private String filename;

    // 构造方法，模拟加载图片（耗时操作）
    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }

    // 模拟从磁盘加载图片
    private void loadFromDisk() {
        System.out.println("[真实操作] 从磁盘加载图片: " + filename);
    }

    // 显示图片
    @Override
    public void display() {
        System.out.println("[真实操作] 显示图片内容: " + filename);
    }

    // 获取图片信息
    @Override
    public String getInfo() {
        return "[真实信息] 图片 '" + filename + "'，分辨率 1920x1080，大小 2.5MB";
    }
}

// 3. 静态代理类
class ImageProxy implements Image {
    private RealImage realImage; // 持有真实对象的引用
    private String filename;

    // 代理类构造方法，只需文件名，不立即加载图片
    public ImageProxy(String filename) {
        this.filename = filename;
        System.out.println("[代理操作] 创建图片代理: " + filename);
    }

    // 显示图片（延迟加载真实对象）
    @Override
    public void display() {
        System.out.println("[代理操作] 准备显示图片...");

        // 延迟加载：只有真正需要时才创建真实对象
        if (realImage == null) {
            realImage = new RealImage(filename);
        }

        // 调用真实对象的方法
        realImage.display();

        System.out.println("[代理操作] 图片显示完毕");
    }

    // 获取图片信息（保护代理）
    @Override
    public String getInfo() {
        // 未加载真实图片时，返回简化信息
        if (realImage == null) {
            return "[代理信息] 图片预览: " + filename;
        }
        // 已加载时，返回真实信息
        return realImage.getInfo();
    }
}

// 4. 动态代理处理器
class LoggingProxyHandler implements InvocationHandler {
    private Object target; // 目标对象

    public LoggingProxyHandler(Object target) {
        this.target = target;
    }

    // 动态增强方法调用
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置增强：记录方法调用日志
        long startTime = System.currentTimeMillis();
        System.out.println("\n[动态代理] 开始调用方法: " + method.getName());

        // 调用目标对象的方法
        Object result = method.invoke(target, args);

        // 后置增强：记录方法执行时间和结果
        long endTime = System.currentTimeMillis();
        System.out.println("[动态代理] 方法 " + method.getName() + " 执行完成");
        System.out.println("[动态代理] 执行时间: " + (endTime - startTime) + "ms");
        System.out.println("[动态代理] 执行结果: " + (result != null ? result : "无返回值"));

        return result;
    }
}

// 5. 客户端测试类
public class ProxyExample {
    public static void main(String[] args) {
        // 测试静态代理
        System.out.println("======= 静态代理测试 =======");
        Image proxyImage = new ImageProxy("风景.jpg");

        // 第一次获取信息：真实对象未创建，返回代理信息
        System.out.println(proxyImage.getInfo());

        // 第一次显示图片：触发真实对象创建和加载
        proxyImage.display();

        // 第二次获取信息：真实对象已存在，返回真实信息
        System.out.println(proxyImage.getInfo());

        // 第二次显示图片：直接使用已创建的真实对象
        proxyImage.display();

        // 测试动态代理
        System.out.println("\n======= 动态代理测试 =======");
        // 创建真实对象
        Image realImage = new RealImage("城市.jpg");

        // 生成动态代理对象
        Image dynamicProxy = (Image) Proxy.newProxyInstance(
                Image.class.getClassLoader(),  // 类加载器
                new Class[]{Image.class},      // 实现的接口
                new LoggingProxyHandler(realImage)  // 代理处理器
        );

        // 通过动态代理调用方法
        dynamicProxy.getInfo();
        dynamicProxy.display();
    }
}

